<template>
  <component is="el-table-column" :label="label">
    <template slot-scope="scope">
            <span v-if="hasChild(scope.row)" @click.prevent="doexpanded(scope.$index,scope.row)">
                <span :style="{paddingLeft : paddingLeft(scope.row)}">
                    <i :class="icon(scope.row)"></i>
                    <i :class="floderIcon(scope.row)" style="padding-right: 7px;"></i>
                </span>
                <span>{{scope.row[prop]}}</span>
            </span>
      <span v-else>
                <span :style="{paddingLeft : paddingLeft(scope.row)}">
                    <i :class="fileIcon" style="padding-right: 7px;padding-left:18px"></i>
                </span>
                <span>{{scope.row[prop]}}</span>
            </span>
    </template>
  </component>
</template>
<script>
  export default {
    name: 'HTreeGrid',
    props: {
      prop: {
        type: String,
        default: "name"
      },
      label: {
        type: String,
        default: "名称"
      },
      width: {
        type: String,
        default: "auto"
      },
      treeKey: {
        type: String,
        default: 'id'
      },
      childNumKey: {
        type: String,
        default: 'childNum'
      },
      parentKey: {
        type: String,
        default: 'parentId'
      },
      levelKey: {
        type: String,
        default: 'level'
      },
      childKey: {
        type: String,
        default: 'children'
      },
      fileIcon: {
        type: String,
        default: 'el-icon-file'
      },
      folderIcon: {
        type: String,
        default: 'el-icon-folder'
      },
      remote: {
        type: Function,
        default: null
      }
    },
    computed: {
      owner() {
        let parent = this.$parent
        while (parent && !parent.tableId) {
          parent = parent.$parent
        }
        return parent
      }
    },
    data() {
      return {loading: false}
    },
    methods: {
      indexOf(v, arr) {
        let has = -1
        for (let i = 0; i < arr.length; i++) {
          if (arr[i] === v) {
            has = i
            break
          }
        }
        return has
      },
      descendantsIds(id, data, parentKey, treeKey) {
        const me = this
        let result = [],
          compare = [id],
          length = -1
        while (length !== compare.length) {
          length = compare.length
          data.forEach(function (item) {
            if (me.indexOf(item[parentKey], compare) > -1 && me.indexOf(item[treeKey], compare) === -1) {
              result.push(item[treeKey])
              compare.push(item[treeKey])
            }
          })
        }
        return result
      },
      hash() {
        return Math.floor(Math.random() * Math.random() * Math.random() * Math.random() * 1000)
      },
      index(hash, data) {
        let i = 0
        while (data[i]) {
          if (data[i].$extra && data[i].$extra.hash === hash) {
            break
          }
          i++
        }
        return i
      },
      floderIcon(row) {
        const expanded = row.$extra && row.$extra.expanded
        const floder = this.folderIcon
        const floder_open = this.folderIcon + '-open'
        return expanded ? floder_open : floder
      },
      hasChild(row) {
        if (row[this.childNumKey] != undefined) {
          return row[this.childNumKey] > 0 ? true : false;
        } else if (row[this.childKey] !== undefined) {
          return row[this.childKey].length > 0
        } else {
          return false
        }
      },
      paddingLeft(row) {
        return (parseInt(row[this.levelKey]) * 14) + 'px'
      },
      icon(row) {
        if (row.$extra && row.$extra.loading === true) return 'el-icon-loading'
        return row.$extra && row.$extra.expanded ? 'el-icon-minus' : 'el-icon-plus'
      },
      doexpanded(index, row) {
        const vm = this
        let data = JSON.parse(JSON.stringify(this.owner.store.states._data))
        if (data[index].$extra === undefined) {
          data[index].$extra = {expanded: true}
        } else {
          data[index].$extra.expanded = !data[index].$extra.expanded
        }
        if (data[index].$extra.expanded) {
          if (this.remote != null) {
            const hash = vm.hash()
            data[index].$extra.expanded = false
            data[index].$extra.hash = hash
            data[index].$extra.loading = true
            vm.owner.store.commit('setData', data)
            this.remote(row, function (result) {
              let list = vm.owner.store.states._data
              let _index = vm.index(hash, list)
              list[_index].$extra = {
                loading: false,
                expanded: !!(result && result.length > 0)
              }
              if (result && result.length > 0) {
                const prefix = list.slice(0, _index + 1)
                let i = 0
                while (i < _index + 1) {
                  list.shift()
                  i++
                }
                list = prefix.concat(result).concat(list)
              } else {
                list[_index][vm.childNumKey] = 0;
              }
              vm.owner.store.commit('setData', list)
            })
          } else {
            const prefix = data.slice(0, index + 1)
            let i = 0
            while (i < index + 1) {
              data.shift()
              i++
            }
            data = prefix.concat(row[vm.childKey]).concat(data)
            this.owner.store.commit('setData', data)
          }
        } else {
          const id = row[vm.treeKey], result = []
          const removeIds = vm.descendantsIds(id, data, vm.parentKey, vm.treeKey)
          data.forEach(function (item) {
            if (vm.indexOf(item[vm.treeKey], removeIds) === -1) {
              result.push(item)
            }
          })
          data = result
          this.owner.store.commit('setData', data)
        }
      }
    }
  }
</script>
<style>
</style>
